package com.uyayo.ucenter.service.impl;

import com.uyayo.framework.common.exception.CodeMultipleException;
import com.uyayo.framework.common.exception.ParentNotFoundException;
import com.uyayo.framework.core.service.impl.BaseServiceImpl;
import com.uyayo.ucenter.entity.GroupResourceRelation;
import com.uyayo.ucenter.entity.Resource;
import com.uyayo.ucenter.mapper.GroupResourceRelationMapper;
import com.uyayo.ucenter.mapper.ResourceMapper;
import com.uyayo.ucenter.model.ResourceCondition;
import com.uyayo.ucenter.service.GroupService;
import com.uyayo.ucenter.service.ResourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;


@Service("resourceService")
public class ResourceServiceImpl extends BaseServiceImpl<Resource> implements ResourceService {

	private final ResourceMapper resourceMapper;

	private final GroupResourceRelationMapper groupResourceRelationMapper;

	private final GroupService groupService;

	@Autowired
	public ResourceServiceImpl(ResourceMapper resourceMapper, GroupResourceRelationMapper groupResourceRelationMapper, GroupService groupService) {
		this.resourceMapper = resourceMapper;
		this.groupResourceRelationMapper = groupResourceRelationMapper;
		this.groupService = groupService;
	}

	@Override
	public List<Resource> selectResource(ResourceCondition resourceCondition) throws  Exception{
		return resourceMapper.selectResource(resourceCondition);
	}

	@Override
	public List<Resource> resourceTreeGrid(Resource resource) {
		List<Resource> resources;
		Example example = new Example(Resource.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo(resource);
		resources = resourceMapper.selectByExample(example);
		return resources;
	}


	@Override
	public List<Resource> selectResourceAll(Resource resource) {
		List<Resource> resources = new ArrayList<>();
		try {
			Example example = new Example(Resource.class);
			resources = resourceMapper.selectByExample(example);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resources;
	}

	@Override
	public int selectCountByParentId(Long parentId) {
		Resource resource = new Resource();
		resource.setParentId(parentId);
		return resourceMapper.selectCount(resource);
	}

	@Override
	public int saveResource(Resource resource) throws CodeMultipleException, ParentNotFoundException {
		Long parentId = resource.getParentId();
		Resource resourceCondition = new Resource();
		resourceCondition.setCode(resource.getCode());
		Resource resourceTest = resourceMapper.selectOne(resourceCondition);
		if(resourceTest!=null){
			throw new CodeMultipleException("Code multiple error!");
		}
		if(!Objects.isNull(parentId)){
			Resource resourceParent = selectByKey(parentId);
			if(resourceParent==null){
				throw new ParentNotFoundException("Parent not found!");
			}
		}
		int count = resourceMapper.insertSelective(resource);
		if(count >0){
			updateHasChildrennToParent(parentId);
			resourceCondition.setCode(resource.getCode());
			resource = resourceMapper.selectOne(resourceCondition);
			groupService.grantGroupResource(String.valueOf(resource.getId()),0L);
		}
		return count;
	}

	/**
	 * 迭代检查选择的上级id是否是自己的子级
	 * @param parentIdOld 原上级id
	 * @param parentIdNew	新上级id
	 * @param resourceChild 子资源
	 * @param resourceParent 父资源
	 */
	private void recursiveCheckParentIsChildren(Long parentIdOld, Long parentIdNew, Resource resourceChild, Resource resourceParent){
		if (selectCountByParentId(resourceChild.getId()) > 0) {
			Example example = new Example(Resource.class);
			Example.Criteria criteria = example.createCriteria();
			criteria.andEqualTo("parentId",resourceChild.getId());
			List<Resource> resources = resourceMapper.selectByExample(example);
			if (!resources.isEmpty()) {
				for(Resource resource:resources){
					if(Objects.equals(resource.getId(),parentIdNew)){
						resourceParent.setParentId(parentIdOld);
						resourceMapper.updateByPrimaryKeySelective(resourceParent);
					}else {
						recursiveCheckParentIsChildren(parentIdOld, parentIdNew, resource, resourceParent);
					}
				}
			}
		}
	}
	@Override
	public int updateResource(Resource resource) throws ParentNotFoundException, CodeMultipleException {

		Resource resourceCondition = new Resource();
		resourceCondition.setCode(resource.getCode());
		Resource resourceTest = resourceMapper.selectOne(resourceCondition);
		if(resourceTest!=null && !Objects.equals(resource.getId(),resourceTest.getId())){
			throw new CodeMultipleException("Code multiple error!");
		}

		Resource resourceOld = selectByKey(resource.getId());

		if(resource.getParentId()==null){
			resource.setParentId(0L);
		}
		Long parentId = resource.getParentId();
		if(parentId!=0){
			//获取修改的父级资源
			Resource resourceParent = selectByKey(parentId);
			if(resourceParent==null){
				throw new ParentNotFoundException("Parent not found!");
			}
			if (selectCountByParentId(resourceOld.getId()) > 0) {
				Example example = new Example(Resource.class);
				Example.Criteria criteria = example.createCriteria();
				criteria.andEqualTo("parentId",resourceOld.getId());
				List<Resource> resources = resourceMapper.selectByExample(example);
				if (!resources.isEmpty()) {
					for(Resource resource_:resources){
						if(Objects.equals(resource_.getId(),parentId)){
							resourceParent.setParentId(resourceOld.getParentId());
							resourceMapper.updateByPrimaryKeySelective(resourceParent);
						}else{
							recursiveCheckParentIsChildren(resourceOld.getParentId(),resource.getParentId(),resource,resourceParent);
						}
					}
				}
			}
		}
		if(selectCountByParentId(resource.getId())>0) {
			resource.setHasChildren(true);
		}else{
			resource.setHasChildren(false);
		}
		int count = resourceMapper.updateByPrimaryKeySelective(resource);
		if(count<=0){
			return count;
		}
		updateHasChildrennToParent(parentId);
		if(resourceOld!=null){
			updateHasChildrennToParent(resourceOld.getParentId());
		}
		return count;
	}

	/**
	 * 修改父资源是否含子资源
	 * @param parentId 父资源id
	 */
	private void  updateHasChildrennToParent(Long parentId){
		if(!Objects.isNull(parentId)){
			Resource resource = new Resource();
			resource.setId(parentId);
			if(selectCountByParentId(parentId)>0) {
				resource.setHasChildren(true);
			}else{
				resource.setHasChildren(false);
			}
			resourceMapper.updateByPrimaryKeySelective(resource);
		}
	}

	@Override
	public int deleteResource(Long id) {

		if (selectCountByParentId(id) > 0) {
			Example example = new Example(Resource.class);
			Example.Criteria criteria = example.createCriteria();
			criteria.andEqualTo("parentId",id);
			List<Resource> resources = resourceMapper.selectByExample(example);
			if (!resources.isEmpty()) {
				for(Resource resource:resources){
					recursiveDelete( resource);
				}
			}
		}
		return delete(id);
	}

	/**
	 * 递归删除资源
	 * @param resource 资源
	 */
	private void recursiveDelete(Resource resource){

		if (selectCountByParentId(resource.getId()) > 0) {
			Example example = new Example(Resource.class);
			Example.Criteria criteria = example.createCriteria();
			criteria.andEqualTo("parentId",resource.getId());
			List<Resource> resources = resourceMapper.selectByExample(example);
			if (!resources.isEmpty()) {
				for(Resource resourceChild:resources){
					recursiveDelete(resourceChild);
				}
			}
		}
		delete(resource.getId());
	}

	public int delete(Long id) {
		Resource resource = resourceMapper.selectByPrimaryKey(id);
		int count = resourceMapper.deleteByPrimaryKey(id);
		if(count<=0){
			return count;
		}
		updateHasChildrennToParent(resource!=null?resource.getParentId():null);

		Example exampleR = new Example(GroupResourceRelation.class);
		Example.Criteria criteriaR = exampleR.createCriteria();
		criteriaR.andEqualTo("resourceId", id);
		groupResourceRelationMapper.deleteByExample(exampleR);
		return count;
	}

	
}
